package indi.yuluo.filter;

import com.alibaba.druid.support.json.JSONUtils;
import indi.yuluo.common.BaseContext;
import indi.yuluo.core.RedisTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Author: yuluo
 * @CreateTime: 2022-08-08  18:26
 * @Description: 用户登录验证过滤器
 */

@Slf4j
@Component
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {

    // 路径匹配器，支持通配符
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    private static final RedisTemplate redisTemplate = new RedisTemplate();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("过滤器初始化！");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        // 将servletRequest转为HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 1、获取本次请求的uri
        String uri = request.getRequestURI();

        log.info("拦截到请求：{}", uri);

        // 需要放行的资源
        String[] uris = new String[]{
                "/",
                "/static/**",
                "/templates/**",
                "/user/login",
                "/user/logout",
                "/user/checkUsername",
                "/user/register",
                "/user/getUserInfoByToken",
                "/favicon.ico",
                "/index.jsp",
                "/code/templates",
                "/code/getCodeType",
                "/problem/getProblemInfo",
                "/problem/getProblemByProblemId",
                "/tran/translate",
                "/discuss/getDiscussInfoByPId",

                // api json文档放行接口
                "/v2/api-docs"
        };

        // 2、判断本次请求是否需要登录
        boolean check = check(uris, uri);

        // 3、如果不需要处理，则直接放行
        if (check) {
            log.info("本次请求不需要处理：{}", uri);
            // 继续执行
            filterChain.doFilter(request, response);
            return;
        }

        // 4、判断登录状态，如果已经登录，则放行
        // 获取请求头信息X-Auth0-Token
        String X_Auth0_Token = request.getHeader("X-Auth0-Token");
        // log.info("请求路径中携带的请求头信息: X_Auth0_Token{}", X_Auth0_Token);

        // 从redis中获取当前登录用户的信息，如果存在，放行
        if (X_Auth0_Token != null && redisTemplate.get(X_Auth0_Token) != null) {
            log.info("用户已经登录,当前登录用户：{}", X_Auth0_Token);
            // 继续执行
            filterChain.doFilter(request, response);
            return;
        }


        // 5、如果未登录，则返回登录失败的结果，通过输出流的方式展示给用户登录或者注册
        response.setCharacterEncoding("GBK");
        response.getWriter().write(JSONUtils.toJSONString("登陆之后才能访问，请登录！"));


    }

    @Override
    public void destroy() {
        log.info("过滤器销毁！");
    }

    /**
     * 路径匹配，检查本次请求是否需要放行
     * @param requestURI
     * @Param uris
     * @return
     */
    public boolean check(String[] uris, String requestURI) {

        boolean flag = false;

        for (String s : uris) {
            // 匹配上为true
            boolean match = PATH_MATCHER.match(s, requestURI);
            if (match) {
                flag = true;
            }
        }

        return flag;
    }
}
